﻿#region Includes
using System;
using OpenTK;
using GingerGL.Math;
#endregion

namespace GingerGL
{
    public class MathHelper2
    {
        #region Constaints
        public const float DefaultTolerance = 0.0001f;
        public const float PIOVER90 = (float)System.Math.PI / 90;
        public const float PIOVER180 = (float)System.Math.PI / 180;
        public const float PIOVER270 = (float)System.Math.PI / 270;
        #endregion

        #region Random Utilities
        static private Random Rand = new Random();
        /// <summary>
        /// Get Random within a Range
        /// </summary>
        static public float RandInRange(float min, float max) { return (float)(Rand.NextDouble() * (max - min) + min); }
        /// <summary>
        /// Get Random within a Range of -1 and 1
        /// </summary>
        static public float RandPlusMinus() { return RandInRange(-1, 1); }
        #endregion

        static public bool Equals(float f1, float f2) { return Equals(f1, f2, DefaultTolerance); }
        static public bool Equals(float f1, float f2, float tolerance) { return System.Math.Abs(f1 - f2) <= tolerance; }
        static public float Hypot(float x, float y) { return (float)System.Math.Sqrt(x * x + y * y); }
        static public float Distance(Vector3 left, Vector3 right)
        {
            return (float)System.Math.Sqrt
            (
                (right.X - left.X) * (right.X - left.X) + 
                (right.Y - left.Y) * (right.Y - left.Y) + 
                (right.Z - left.Z) * (right.Z - left.Z)
            );
        }
        static public float Distance(Vector2 left, Vector2 right)
        {
            return (float)System.Math.Sqrt
            (
                (right.X - left.X) * (right.X - left.X) +
                (right.Y - left.Y) * (right.Y - left.Y)
            );
        }
        static public float DistanceSquared(Vector3 left, Vector3 right)
        {
            return 
                (right.X - left.X) * (right.X - left.X) + 
                (right.Y - left.Y) * (right.Y - left.Y) + 
                (right.Z - left.Z) * (right.Z - left.Z);
        }
        static public float DistanceSquared(Vector2 left, Vector2 right)
        {
            return
                (right.X - left.X) * (right.X - left.X) +
                (right.Y - left.Y) * (right.Y - left.Y);
        }
        static public Vector3 Vector3FromAngle(float angle)
        {
            return new Vector3
            (
                (float)System.Math.Cos(OpenTK.MathHelper.DegreesToRadians(angle)),
                (float)System.Math.Sin(OpenTK.MathHelper.DegreesToRadians(angle)),
                0
            );
        }
        static public Vector2 Vector2FromAngle(float angle)
        {
            return new Vector2
            (
                (float)System.Math.Cos(OpenTK.MathHelper.DegreesToRadians(angle)),
                (float)System.Math.Sin(OpenTK.MathHelper.DegreesToRadians(angle))
            );
        }
        static public Plane[] GetPlanes(BoundingFrustum frustum)
        {
            Plane[] l = new Plane[6];
            l[0] = frustum.Near;
            l[1] = frustum.Left;
            l[2] = frustum.Right;
            l[3] = frustum.Top;
            l[4] = frustum.Bottom;
            l[5] = frustum.Far;
            return l;
        }
        static public float CapAngle(float Angle)
        {
            if (Angle > 360f) Angle -= 360f;
            if (Angle < 0f) Angle += 360f;
            return Angle;
        }
        public static float CosDeg(float Angle) { return (float)System.Math.Cos((double)(Angle * PIOVER180)); }
        public static float SinDeg(float Angle) { return (float)System.Math.Sin((double)(Angle * PIOVER180)); }
    }
}
